home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume23 / pty / part04 < prev    next >
Encoding:
Internet Message Format  |  1991-01-08  |  54.4 KB

  1. Path: j.cc.purdue.edu!mentor.cc.purdue.edu!noose.ecn.purdue.edu!samsung!uunet!papaya.bbn.com!rsalz
  2. From: rsalz@bbn.com (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v23i034:  Run a program under a pty session, Part04/06
  5. Message-ID: <2884@litchi.bbn.com>
  6. Date: 10 Oct 90 14:16:54 GMT
  7. Organization: BBN Systems and Technologies, Cambridge MA
  8. Lines: 1868
  9. Approved: rsalz@uunet.UU.NET
  10. X-Checksum-Snefru: cceeda5b e213dfb2 d9db214c 1b846bab
  11.  
  12. Submitted-by: Dan Bernstein <brnstnd@kramden.acf.nyu.edu>
  13. Posting-number: Volume 23, Issue 34
  14. Archive-name: pty/part04
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  21. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  22. # Contents:  COPYRIGHT QUESTIONS TESTS patch/Makefile patch/README
  23. #   sig.c slave.c texts.c util/biff.c util/sesslist.c util/sessuser.1
  24. #   util/sessuser.c util/sessutil.c util/write.c util/xsessutil.c
  25. # Wrapped by rsalz@litchi.bbn.com on Wed Oct 10 10:11:39 1990
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. echo If this archive is complete, you will see the following message:
  28. echo '          "shar: End of archive 4 (of 6)."'
  29. if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'COPYRIGHT'\"
  31. else
  32.   echo shar: Extracting \"'COPYRIGHT'\" \(2129 characters\)
  33.   sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
  34. Xpty version 3.001, August 21, 1990.
  35. XCopyright (c) 1990, Daniel J. Bernstein.
  36. XAll rights reserved.
  37. X
  38. XI want this program to be distributed freely in original form.
  39. X
  40. XOnce you've received a legal copy of this program, you can use it.
  41. XForever. Nobody can take that right away from you. You can make changes
  42. Xand backup copies for your use (or, if you're an organization, for the
  43. Xuse of everyone in the organization). You can distribute patches (though
  44. Xnot patched versions). You'd have all these rights even if I didn't tell
  45. Xyou about them.
  46. X
  47. XCopyright law gives an author the exclusive right to copy and distribute his
  48. Xworks. So that you don't have to worry about these legalities, I grant you the
  49. Xright to make and distribute exact and complete copies of this program.
  50. X
  51. XOn the other hand, I don't want this program sold without my permission.
  52. XUnless I give you permission, you may not charge for copies. You may charge for
  53. Xdistribution---but only if you first warn the recipient that the code is free,
  54. Xand tell him where you got it from.
  55. X
  56. XI don't want this program distributed without my name on it. I also don't
  57. Xwant lots of different versions running around, so unless I give you permission
  58. Xyou can't send out a modified version. It's perfectly all right to send other
  59. Xpeople a description of how to make your changes (i.e., a patch), because then
  60. Xeach recipient knows firsthand what patches he's installed, and I won't go
  61. Xchasing ghosts. (An author has no right to control patches in any case.)
  62. X
  63. XIf you run an archive site: When you receive a patch supposedly from me, do you
  64. Xapply it to the original package and repackage it? I encourage you to change
  65. Xyour policy, if for no other reason than to give recipients a fallback in case
  66. Xof buggy patches. If you're really set on this, how about including the patches
  67. Xas separate, unapplied PATCHnn files inside the package? That's fine by me.
  68. X
  69. XIf you have questions about this program or about this notice, or if you
  70. Xwould like additional rights beyond those granted above, or if you have
  71. Xa patch that you don't mind sharing, please contact me on the Internet
  72. Xat brnstnd@acf10.nyu.edu.
  73. END_OF_FILE
  74.   if test 2129 -ne `wc -c <'COPYRIGHT'`; then
  75.     echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
  76.   fi
  77.   # end of 'COPYRIGHT'
  78. fi
  79. if test -f 'QUESTIONS' -a "${1}" != "-c" ; then 
  80.   echo shar: Will not clobber existing file \"'QUESTIONS'\"
  81. else
  82.   echo shar: Extracting \"'QUESTIONS'\" \(4202 characters\)
  83.   sed "s/^X//" >'QUESTIONS' <<'END_OF_FILE'
  84. XI selected the questions below from articles posted to the USENET
  85. Xnewsgroup comp.unix.questions. All the questions are reasonably easy to
  86. Xanswer with pty and not too easy to answer with other widely available
  87. Xtools. So I hope this file is useful, and I hope other software authors
  88. Xadopt the QUESTIONS idea.
  89. X
  90. XOrganization: question, one-sentence answer, further details of
  91. Xanswer, why the question normally poses a problem, and why the answer
  92. Xgiven solves the problem.
  93. X
  94. X
  95. X1. How to redirect telnet's input?
  96. X
  97. XRun pty telnet instead of telnet. Caveat: telnet stupidly flushes its
  98. Xinput at connect time, so be careful not to flood it; instead do
  99. Xsomething like % (sleep 5;echo help;echo quit) | pty telnet whatever 25.
  100. X(Try it!) The five-second pause should be enough. For a more
  101. Xsophisticated (and reliable) technique, see #4 below.
  102. X
  103. XThe problem here is that telnet wants to take its input from a terminal.
  104. XMost other interactive applications (e.g., editors) feel the same way
  105. Xabout stdin, stdout, and stderr. pty solves this by setting input,
  106. Xoutput, and error all to the pseudo-terminal.
  107. X
  108. X
  109. X2. How to redirect su's input?
  110. X
  111. Xpty su < input, of course. (I certainly don't recommend putting your
  112. Xpassword in plaintext to be fed to su, but it can be done!) Note that
  113. Xsome su's flush their input; solve this as in #1 above or #4 below.
  114. X
  115. XThe problem is that su opens /dev/tty for its input. Many other programs
  116. Xuse /dev/tty explicitly for input and output; how do you redirect them?
  117. Xpty solves this because a program under a pseudo-terminal refers to that
  118. Xterminal when it opens /dev/tty.
  119. X
  120. X
  121. X3. How to make sed 's/foo/bar/g' | more work?
  122. X
  123. Xpty -0 sed 's/foo/bar/g' | more. You can abbreviate pty -0 as condom.
  124. X
  125. XThe problem is that sed uses stdio. stdio checks whether its output is a
  126. Xterminal; if not, it buffers a block of data inside the program. To see
  127. Xthis in action, try the original % sed 's/foo/bar/g' | more; unless you
  128. Xtype a lot of input, sed will keep buffering its output, so you'll never
  129. Xsee anything.
  130. X
  131. Xpty solves the stdio buffer problem because a program under stdio does
  132. Xhave a terminal (the pseudo-terminal) as output. So stdio buffers only a
  133. Xline at a time.
  134. X
  135. X
  136. X4. How to start a program, respond to its prompts, give the correct
  137. X   replies, and catch the output?
  138. X
  139. XOn a machine with named pipes created by mknod foo p:
  140. X
  141. X  #!/bin/sh
  142. X  # Generic reader-writer.
  143. X  (umask 077;mknod input p;mknod output p)
  144. X  pty -0 program args < input | pty -0 tee record > output &
  145. X  exec 4>input 5<output
  146. X  # Now read prompts from <&5 and write replies to >&4.
  147. X  # A transcript is kept in record.
  148. X
  149. XAnother solution is to create two (unnamed) pipes, then stick pty
  150. Xbetween them as above. This requires C code but is more portable.
  151. X
  152. XThe problems here are just the problems in #1-#3 above.
  153. X
  154. X
  155. X5. How to fool rn into processing KILL files in the background?
  156. X
  157. Xpty -T rn &. This does have one deficiency: control characters like ^C,
  158. X^Z, and so on affect pty rather than rn. (That's what -T does.) This
  159. Xdoesn't matter for rn, but pty -T vi verylongfile definitely doesn't
  160. Xwork the right way. To pass control characters through, start with
  161. X
  162. X  % pty -s sh -c 'sessname;disconnect;pty vi verylongfile'
  163. X
  164. X(pty -s can be abbreviated as sess.) Then watch the vi process with ps
  165. Xor by typing pty -sT reconnect xx, watching, then pressing ^C, where xx
  166. Xis the session name (pty extension). When you want to reconnect and pass
  167. Xcontrol characters to vi, type % pty -s reconnect xx. From that point
  168. Xit'll feel just like a normal vi.
  169. X
  170. XThe problem is that rn---like all character-based interactive
  171. Xapplications---wants to change the tty mode to read one character at a
  172. Xtime instead of one line at a time. The tty driver doesn't let it do
  173. Xthis in the background. pty -T rn solves this because rn is really in
  174. Xthe foreground under the pty.
  175. X
  176. X
  177. X6. How to get terminal speed from shell script?
  178. X
  179. X"`pty stty speed`", assuming fd 0 or fd 2 is the tty.
  180. X
  181. XThe problem is that a straight `stty speed` pipes stty's output away
  182. Xfrom your terminal and back into your shell. Many versions of stty
  183. Xassume that their output points to the terminal, so they blow up. pty
  184. Xsolves this because it copies information from the real terminal to the
  185. Xpseudo-terminal.
  186. END_OF_FILE
  187.   if test 4202 -ne `wc -c <'QUESTIONS'`; then
  188.     echo shar: \"'QUESTIONS'\" unpacked with wrong size!
  189.   fi
  190.   # end of 'QUESTIONS'
  191. fi
  192. if test -f 'TESTS' -a "${1}" != "-c" ; then 
  193.   echo shar: Will not clobber existing file \"'TESTS'\"
  194. else
  195.   echo shar: Extracting \"'TESTS'\" \(3657 characters\)
  196.   sed "s/^X//" >'TESTS' <<'END_OF_FILE'
  197. X#!/bin/sh
  198. X# This is a shell script. Feed it to sh.
  199. Xecho '
  200. XHi, and welcome to the pty test script.
  201. X
  202. XAs in installation, I'\''m not actually going to do anything.
  203. XI'\''ll just guide you through a few (non-comprehensive) tests.
  204. X
  205. XRemember: Like all software, pty comes without warranty, to the extent
  206. Xpermitted by applicable law. Use it at your own risk.
  207. X'
  208. X
  209. Xecho '----- Press return to continue. ' | tr -d '\012'; read contline
  210. X
  211. Xecho '
  212. XFirst, just try % pty vi. You shouldn'\''t be able to tell the
  213. Xdifference between this and a normal vi; stopping and restarting should
  214. Xwork perfectly, as should normal typing.
  215. X'
  216. X
  217. Xecho '----- Press return to continue. ' | tr -d '\012'; read contline
  218. X
  219. Xecho '
  220. XNext, try % pty -0 tr \! \? | pty vi. This should work just like the
  221. Xlast vi, with the following differences: 1. Stopping will require two
  222. X^Zs, because csh idiotically doesn'\''t think a pipeline has stopped
  223. Xwhen just its second component stops. 2. Exiting will require an extra
  224. Xline to feed through tr, so that it gets a broken pipe; this is more
  225. Xsensible than #1. 3. All exclamation points will be turned into question
  226. Xmarks. This has obvious applications. :w /dev/null helps to escape.
  227. X'
  228. X
  229. Xecho '----- Press return to continue. ' | tr -d '\012'; read contline
  230. X
  231. Xecho '
  232. XContinuing along the lines of how to stick annoying programs into a
  233. Xpipe, try % pty -0 sed '\''s/foo/bar/g'\'' | more. (Remember that sed outputs
  234. Xeach line only after it receives the next.) Try the same thing without
  235. Xpty.
  236. X
  237. XNote that pty -0 can be abbreviated as condom.
  238. X'
  239. X
  240. Xecho '----- Press return to continue. ' | tr -d '\012'; read contline
  241. X
  242. Xecho '
  243. XNext, try using the replacement script program. % script. Type various
  244. Xcommands; try logging on to another terminal and using talk; observe
  245. Xthat you'\''re listed in /etc/utmp. Try the clones of tty, mesg, biff,
  246. Xu, wall, who, lock. (Try them under a non-pty session too.)
  247. X'
  248. X
  249. Xecho '----- Press return to continue. ' | tr -d '\012'; read contline
  250. X
  251. Xecho '
  252. XMuch of the fun of pty is in disconnecting and reconnecting sessions.
  253. XIf you'\''re ambitious, try % sess sh. ^Z will get you out and back in.
  254. XTry sessname without an argument; try it with an argument. Try sesslist.
  255. XFinally, try $ disconnect, and go on to the next part of this script.
  256. X'
  257. X
  258. Xecho '----- Press return to continue. ' | tr -d '\012'; read contline
  259. X
  260. Xecho '
  261. XAlthough it looks like your sh session has finished, it'\''s actually
  262. Xsitting in limbo, waiting for you to reconnect. You can still see it
  263. Xunder who, sesslist, or ps. Now try % sess reconnect q7  or whatever the
  264. Xextension of the disconnected session is; you should be right back in.
  265. X
  266. XYou can try the same thing by actually hanging up your connection, then
  267. Xlogging in again and reconnecting.
  268. X'
  269. X
  270. Xecho '----- Press return to continue. ' | tr -d '\012'; read contline
  271. X
  272. Xecho '
  273. XFor one final trick,
  274. X% sess sh
  275. X$ PS1=FOO.; disconnect
  276. X% sess sh
  277. X$ sesslist
  278. X...
  279. X$ PS1=BAR.; reconnect q7; disconnect
  280. XFOO.reconnect p4; disconnect
  281. XBAR.reconnect q7; disconnect
  282. XFOO.echo Neat, flipping right back and forth!
  283. X'
  284. X
  285. Xecho '----- Press return to continue. ' | tr -d '\012'; read contline
  286. X
  287. Xecho '
  288. XThat'\''s it! Make sure the manual pages and programs are easily
  289. Xaccessible. To repeat a note from INSTALL:
  290. X
  291. XIf you make it through installation and testing and get pty running,
  292. Xplease send a note to the author, Dan Bernstein, on the Internet
  293. Xat brnstnd@nyu.edu. Let him know your computer model, OS version, and
  294. Xwhat changes you had to make. If you have any trouble, please also get
  295. Xin touch with the author. If you have a different kind of system with
  296. Xpseudo-terminal support that could use a pty port, the author would
  297. Xlove to hear about it.
  298. X
  299. XThanks!
  300. X'
  301. END_OF_FILE
  302.   if test 3657 -ne `wc -c <'TESTS'`; then
  303.     echo shar: \"'TESTS'\" unpacked with wrong size!
  304.   fi
  305.   # end of 'TESTS'
  306. fi
  307. if test -f 'patch/Makefile' -a "${1}" != "-c" ; then 
  308.   echo shar: Will not clobber existing file \"'patch/Makefile'\"
  309. else
  310.   echo shar: Extracting \"'patch/Makefile'\" \(2813 characters\)
  311.   sed "s/^X//" >'patch/Makefile' <<'END_OF_FILE'
  312. Xtpat: tpat1
  313. X
  314. Xtpat1: igntt
  315. X    echo '1. Get the new telnetd from ucbarpa.berkeley.edu:' 1>&2
  316. X    echo 'This command will retrieve telnet.90.06.28.tar.Z.' 1>&2
  317. X    echo 'To execute it, just press return.' 1>&2
  318. X    echo 'To continue, just make tpat2 > /dev/null.' 1>&2
  319. X    ./igntt tiocsti 'ftp -n 128.32.130.11 < TELNET.FTP'
  320. X
  321. Xtpat2: igntt
  322. X    echo '2. Unpack telnetd:' 1>&2
  323. X    echo 'This is self-explanatory. You may want tar xvf to see a file list.' 1>&2
  324. X    echo 'To continue, just make tpat3 > /dev/null.' 1>&2
  325. X    if test -f telnet.90.06.28.tar.Z ;\
  326. X    then ./igntt tiocsti 'uncompress < telnet.90.06.28.tar.Z | tar xf -' ;\
  327. X    else echo 'Aack! telnet.90.06.28.tar.Z doesn'\''t exist!' ;\
  328. X    fi
  329. X
  330. Xtpat3: igntt
  331. X    echo '3. Apply these patches, and check that they'\''re safe:' 1>&2
  332. X    echo 'If all goes well, you should see a flood of successful patch output.' 1>&2
  333. X    echo 'The unifdefs are to check the safety of the patches;' 1>&2
  334. X    echo 'as you will see, the patches do nothing with USEPTY undefined.' 1>&2
  335. X    echo 'To continue, just make tpat4 > /dev/null.' 1>&2
  336. X    if test -d telnet.90.06.28 ;\
  337. X    then ./igntt tiocsti 'cd telnet.90.06.28/telnetd; ' \
  338. X                 'patch < ../../telnetd.90.06.28.patch; ' \
  339. X                 'unifdef -UUSEPTY sys_term.c | cmp - sys_term.c.orig; ' \
  340. X                 'unifdef -UUSEPTY telnetd.c | cmp - telnetd.c.orig; ' \
  341. X                 'unifdef -UUSEPTY pathnames.h | cmp - pathnames.h.orig; ' \
  342. X                 'cd ../..' ;\
  343. X    fi
  344. X
  345. Xtpat4: igntt
  346. X    echo '4. Check the pty pathname and fix it if necessary:' 1>&2
  347. X    echo 'Since there is no standard like /inst for where programs go,' 1>&2
  348. X    echo 'you had better make sure telnetd's pathnames.h is correct.' 1>&2
  349. X    echo 'To continue, just make tpat5 > /dev/null.' 1>&2
  350. X    ./igntt tiocsti 'grep PATH_PTY telnet.90.06.28/telnetd/pathnames.h'
  351. X
  352. Xtpat5: igntt
  353. X    echo '5. Add sock.o and sock.h symlinks:' 1>&2
  354. X    echo 'This is self-explanatory.' 1>&2
  355. X    echo 'To continue, just make tpat6 > /dev/null.' 1>&2
  356. X    ./igntt tiocsti 'ln -s ../../../sock.{h,o} telnet.90.06.28/telnetd'
  357. X
  358. Xtpat6: igntt
  359. X    echo '6. Preparing for compile: Edit Makefile and Makefile.generic.' 1>&2
  360. X    echo 'You must at least add -DUSEPTY to CFLAGS and sock.o to OBJS' 1>&2
  361. X    echo 'in Makefile.generic.' 1>&2
  362. X    echo 'telnetd isn'\''t too high on the portability scale, so you' 1>&2
  363. X    echo 'may have to make quite a few more changes.' 1>&2
  364. X    echo 'Anyway, make tpat7 > /dev/null to continue.' 1>&2
  365. X    ./igntt tiocsti 'vi telnet.90.06.28/telnetd/Makefile.generic'
  366. X
  367. Xtpat7: igntt
  368. X    echo '7. Compile!' 1>&2
  369. X    echo 'As explained in the telnetd source documentation, you have' 1>&2
  370. X    echo 'to provide the machine name to make. Under SunOS 4.0.3,' 1>&2
  371. X    echo 'you can just press return here.' 1>&2
  372. X    echo 'When and if this succeeds, go to step 8 of README.' 1>&2
  373. X    ./igntt tiocsti '( cd telnet.90.06.28/telnetd; (date;make sun4.0) >>&Makelog ) &'
  374. X
  375. Xigntt: igntt.c
  376. X    cc -o igntt igntt.c
  377. END_OF_FILE
  378.   if test 2813 -ne `wc -c <'patch/Makefile'`; then
  379.     echo shar: \"'patch/Makefile'\" unpacked with wrong size!
  380.   fi
  381.   # end of 'patch/Makefile'
  382. fi
  383. if test -f 'patch/README' -a "${1}" != "-c" ; then 
  384.   echo shar: Will not clobber existing file \"'patch/README'\"
  385. else
  386.   echo shar: Extracting \"'patch/README'\" \(4777 characters\)
  387.   sed "s/^X//" >'patch/README' <<'END_OF_FILE'
  388. XAt the moment, the only thing here is telnetd.90.06.28.patch. It's
  389. Xpublic domain.
  390. X
  391. Xtelnetd.90.06.28.patch is a safe patch to the telnetd source in
  392. Xtelnet.90.06.28 on ucbarpa.berkeley.edu (128.32.130.11). ``Safe'' means
  393. Xthat every file compiles exactly the same if USEPTY is not defined;
  394. Xyou can apply the patch without any worry of messing up your source.
  395. X
  396. XWhat follows is an outline of how to apply the patch and enable it. A
  397. Xpatched telnetd uses pty to manage sessions, so that users can easily
  398. Xdisconnect and reconnect login sessions. You *must* have compiled file
  399. Xdescriptor passing into pty for this to work; telnetd needs to get the
  400. Xpseudo-terminal descriptors from pty. Given fd passing, though, the
  401. Xpatched telnetd gives you the *full* efficiency of the unpatched
  402. Xversion, even for reconnected sessions!
  403. X
  404. X
  405. XHere's what to do. If you have the tiocsti utility installed, try
  406. X``make > /dev/null'' in this directory; or just read through these
  407. Xinstructions. The usual warning: Like all software, this comes with
  408. Xall warranties disclaimed, to the extent permitted by applicable law.
  409. X
  410. X
  411. X1. Get the new telnetd:
  412. X
  413. X  % ftp -n 128.32.130.11 < TELNET.FTP
  414. X
  415. X2. Unpack it:
  416. X
  417. X  % uncompress < telnet.90.06.28.tar.Z | tar xf -
  418. X
  419. X3. Apply these patches, and check that they're safe:
  420. X
  421. X  % cd telnet.90.06.28/telnetd
  422. X  % patch < ../../telnetd.90.06.28.patch
  423. X  % unifdef -UUSEPTY sys_term.c | cmp - sys_term.c.orig
  424. X  % unifdef -UUSEPTY telnetd.c | cmp - telnetd.c.orig
  425. X  % unifdef -UUSEPTY pathnames.h | cmp - pathnames.h.orig
  426. X  % cd ../..
  427. X
  428. X4. Check the pty pathname and fix it if necessary:
  429. X
  430. X  % grep PATH_PTY telnet.90.06.28/telnetd/pathnames.h
  431. X
  432. X5. Add sock.o and sock.h symlinks:
  433. X
  434. X  % ( cd telnet.90.06.28/telnetd; ln -s ../../../sock.{o,h} . )
  435. X
  436. X6. When you want to compile the patched version: Add sock.o to OBJS
  437. X   and -DUSEPTY to CCOPTS in Makefile.generic. Change whatever else
  438. X   necessary to get telnetd to compile.
  439. X
  440. X7. Compile! On a Sun 4 under SunOS 4.0.3, for example, you just
  441. X   ``make sun4.0'' in the telnetd directory.
  442. X
  443. X8. If you actually survive telnetd's incompatibilities and get it to
  444. X   compile, keep reading.
  445. X
  446. X
  447. XThe reason this telnetd is so big is that it supports Linemode, a bold
  448. Xattempt to cut the Internet load from all the fast typists in the world
  449. Xby a third or even a half.
  450. X
  451. XIf you're bored, compile the telnet client as well.
  452. X
  453. X
  454. XAnyway, the telnetd you just compiled supports pty. You probably don't
  455. Xwant to replace your original telnetd, because if something goes wrong
  456. Xthen you need to log in again. Also, your telnetd may have special
  457. Xfeatures for your machine. Instead, take the gradual upgrade path: Put
  458. Xtelnetd into /usr/local/telnetd.pty, add a new ``tpt'' port to
  459. X/etc/services, and add this line to /etc/inetd.conf:
  460. X
  461. Xtpt    stream    tcp    nowait    root    /usr/local/telnetd.pty    telnetd
  462. X
  463. X(On older machines, ``root'' wouldn't be there; imitate the telnet line
  464. Xto figure out the right format. If you have the better interface of
  465. Xattachport, use it instead.) kill -HUP the inetd process so that it will
  466. Xreread inetd.conf.
  467. X
  468. X
  469. XNow try connecting to the tpt port rather than 23 (instead of telnet X,
  470. Xdo telnet X tpt). You should end up talking to the new telnetd, a clean
  471. Xlogin, and (best of all) a pty session. (The most common problem: Lines
  472. Xdon't appear until after you press return. This means that your old
  473. Xtelnet doesn't support Linemode; type ``^]mo ch'' to fix it. Also send
  474. Xcomplaints about the incompatibilities to dab@cray.com.) If the
  475. Xconnection hangs for more than a second or produces weird results,
  476. Xyou're probably out of luck; pty's author would appreciate hearing about
  477. Xyour experiences.
  478. X
  479. XIf all goes well (whew!) you can log in normally, just as if you're
  480. Xconnected to the old telnetd. Once you're in a shell, try using the pty
  481. Xutilities, as if you were under sess. You should find that the commands
  482. Xfail unless you're root, because that session was started by root rather
  483. Xthan you. (This points out a failure in the telnetd-login-utmp model.)
  484. XTo gain control of the session, type ``sessuser'' and pray. If nothing
  485. Xgoes wrong, you can then disconnect the session, set up a reconnect to
  486. Xanother one, use sessname and sesslist, etc. Yahoo! Tell your users!
  487. XReplace your old telnetd with the new one! Add sessuser to the default
  488. X.cshrc! And please send a note to brnstnd@nyu.edu about your success.
  489. X
  490. X
  491. XNote that many popular versions of login use an annoying heuristic to
  492. Xsave a few microseconds in updating /etc/utmp. The result is, first,
  493. Xthat there's a race condition that can break down /etc/utmp on heavily
  494. Xloaded machines; and second, that login and pty have different views of
  495. X/etc/utmp. For this reason, pty is invoked with -xR to search for ptys
  496. Xin order. You may even want to make -xR default (by setting flagxrandom
  497. Xto 0 in pty's globals.c). Sigh.
  498. END_OF_FILE
  499.   if test 4777 -ne `wc -c <'patch/README'`; then
  500.     echo shar: \"'patch/README'\" unpacked with wrong size!
  501.   fi
  502.   # end of 'patch/README'
  503. fi
  504. if test -f 'sig.c' -a "${1}" != "-c" ; then 
  505.   echo shar: Will not clobber existing file \"'sig.c'\"
  506. else
  507.   echo shar: Extracting \"'sig.c'\" \(4549 characters\)
  508.   sed "s/^X//" >'sig.c' <<'END_OF_FILE'
  509. X/* Copyright 1990, Daniel J. Bernstein. All rights reserved. */
  510. X
  511. X#include "config.h"
  512. X#include <sys/time.h>
  513. X#include "sig.h"
  514. X
  515. X/* This is a stripped-down signal library, with automatic critical */
  516. X/* sections around every signal handler. As long as no signal handler */
  517. X/* has to pause waiting for another signal, this works beautifully */
  518. X/* and prevents all races. */
  519. X
  520. Xstatic int queued[SIGNUM];
  521. Xstatic int quo[SIGNUM];
  522. Xstatic sig_syshandler orig[SIGNUM];
  523. Xstatic sig_handler handler[SIGNUM];
  524. X
  525. Xstatic sig_syshandler signalv(s,h)
  526. Xregister sig_num s;
  527. Xregister sig_syshandler h;
  528. X{
  529. X return signal(s,h);
  530. X}
  531. X
  532. Xstatic int crit = 0;
  533. X
  534. Xstatic void handle(i)
  535. Xregister sig_num i;
  536. X{
  537. X if (crit)
  538. X   queued[i] = 1;
  539. X else
  540. X  {
  541. X   register int q;
  542. X   register sig_num j;
  543. X
  544. X   crit = 1; (void) handler[i](i); queued[i] = 0; crit = 0;
  545. X   do for (j = q = 0;j < SIGNUM;j++) if (queued[j])
  546. X    {
  547. X     crit = q = 1;
  548. X     if (j != i) (void) handler[j](j);
  549. X     queued[j] = 0; crit = 0;
  550. X    }
  551. X   while (q);
  552. X  }
  553. X}
  554. X
  555. X/* To see why handle() works: First, crit can be considered a local
  556. Xvariable, because handle() is the only routine that modifies it, and
  557. Xhandle() always leaves crit the same. Second, crit is 1 while any
  558. Xhandler is called, and then any simultaneous handle()s will simply
  559. Xqueue. Hence handlers are mutually exclusive. Third, when handle() is
  560. Xcalled with crit == 0, it can only exit after going through an entire j
  561. Xloop with no queued[]s true. Fourth, if all queued[]s are false through
  562. Xthat j loop, then crit is not set by handle() during that loop. Finally,
  563. Xif crit is 0, handle() will exit with no queued signals: this is true by
  564. Xinduction from the previous observations. */
  565. X
  566. X
  567. X/* There is unfortunately no guarantee that a signal handler as */
  568. X/* passed to signal() will receive its signal number as its first */
  569. X/* argument. We do make that guarantee. */
  570. X
  571. X#define HAN(s,h) SIGRET_TYPE h() { handle(s); }
  572. X
  573. XHAN(0,han0);   HAN(1,han1);   HAN(2,han2);   HAN(3,han3);
  574. XHAN(4,han4);   HAN(5,han5);   HAN(6,han6);   HAN(7,han7);
  575. XHAN(8,han8);   HAN(9,han9);   HAN(10,han10); HAN(11,han11);
  576. XHAN(12,han12); HAN(13,han13); HAN(14,han14); HAN(15,han15);
  577. XHAN(16,han16); HAN(17,han17); HAN(18,han18); HAN(19,han19);
  578. XHAN(20,han20); HAN(21,han21); HAN(22,han22); HAN(23,han23);
  579. XHAN(24,han24); HAN(25,han25); HAN(26,han26); HAN(27,han27);
  580. XHAN(28,han28); HAN(29,han29); HAN(30,han30); HAN(31,han31);
  581. X
  582. Xstatic sig_syshandler han[32] =
  583. X  { han0 ,han1 ,han2 ,han3 ,han4 ,han5 ,han6 ,han7 ,
  584. X    han8 ,han9 ,han10,han11,han12,han13,han14,han15,
  585. X    han16,han17,han18,han19,han20,han21,han22,han23,
  586. X    han24,han25,han26,han27,han28,han29,han30,han31
  587. X  } ;
  588. X
  589. X#define QUE(s,h) SIGRET_TYPE h() { quo[s] = 1; }
  590. X
  591. XQUE(0,que0);   QUE(1,que1);   QUE(2,que2);   QUE(3,que3);
  592. XQUE(4,que4);   QUE(5,que5);   QUE(6,que6);   QUE(7,que7);
  593. XQUE(8,que8);   QUE(9,que9);   QUE(10,que10); QUE(11,que11);
  594. XQUE(12,que12); QUE(13,que13); QUE(14,que14); QUE(15,que15);
  595. XQUE(16,que16); QUE(17,que17); QUE(18,que18); QUE(19,que19);
  596. XQUE(20,que20); QUE(21,que21); QUE(22,que22); QUE(23,que23);
  597. XQUE(24,que24); QUE(25,que25); QUE(26,que26); QUE(27,que27);
  598. XQUE(28,que28); QUE(29,que29); QUE(30,que30); QUE(31,que31);
  599. X
  600. Xstatic sig_syshandler que[32] =
  601. X  { que0 ,que1 ,que2 ,que3 ,que4 ,que5 ,que6 ,que7 ,
  602. X    que8 ,que9 ,que10,que11,que12,que13,que14,que15,
  603. X    que16,que17,que18,que19,que20,que21,que22,que23,
  604. X    que24,que25,que26,que27,que28,que29,que30,que31
  605. X  } ;
  606. X
  607. X
  608. Xvoid sig_init()
  609. X{
  610. X sig_num i;
  611. X
  612. X for (i = 0;i < SIGNUM;i++)
  613. X   quo[i] = 0;
  614. X for (i = 0;i < SIGNUM;i++)
  615. X   orig[i] = signalv(i,que[i]);
  616. X}
  617. X
  618. Xvoid sig_restore()
  619. X{
  620. X sig_num i;
  621. X
  622. X for (i = 0;i < SIGNUM;i++)
  623. X   (void) signalv(i,orig[i]);
  624. X}
  625. X
  626. Xvoid sig_handle(s)
  627. Xsig_num s;
  628. X{
  629. X if (quo[s])
  630. X   han[s]();
  631. X (void) signalv(s,han[s]);
  632. X quo[s] = 0;
  633. X}
  634. X
  635. Xvoid sig_ignore(s)
  636. Xsig_num s;
  637. X{
  638. X (void) signalv(s,SIG_IGN);
  639. X}
  640. X
  641. Xvoid sig_default(s)
  642. Xsig_num s;
  643. X{
  644. X (void) signalv(s,SIG_DFL);
  645. X}
  646. X
  647. Xvoid sig_sethandler(s,h)
  648. Xsig_num s;
  649. Xsig_handler h;
  650. X{
  651. X handler[s] = h;
  652. X}
  653. X
  654. X#ifdef SIGINTERRUPT
  655. Xvoid sig_interrupt()
  656. X{
  657. X register sig_num s;
  658. X
  659. X for (s = 0;s < SIGNUM;s++)
  660. X   (void) siginterrupt(s,1);
  661. X}
  662. X#endif
  663. X
  664. Xvoid sig_startring()
  665. X{
  666. X struct itimerval it;
  667. X
  668. X it.it_value.tv_sec = it.it_interval.tv_sec = 0;
  669. X it.it_value.tv_usec = it.it_interval.tv_usec = 10000;
  670. X (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
  671. X}
  672. X
  673. Xvoid sig_stopring()
  674. X{
  675. X struct itimerval it;
  676. X
  677. X it.it_value.tv_sec = it.it_interval.tv_sec = 0;
  678. X it.it_value.tv_usec = it.it_interval.tv_usec = 0;
  679. X (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
  680. X}
  681. X
  682. X/*ARGSUSED*/
  683. Xvoid nothing(i)
  684. Xsig_num i;
  685. X{
  686. X ; /* that's right, absolutely nothing. */
  687. X}
  688. END_OF_FILE
  689.   if test 4549 -ne `wc -c <'sig.c'`; then
  690.     echo shar: \"'sig.c'\" unpacked with wrong size!
  691.   fi
  692.   # end of 'sig.c'
  693. fi
  694. if test -f 'slave.c' -a "${1}" != "-c" ; then 
  695.   echo shar: Will not clobber existing file \"'slave.c'\"
  696. else
  697.   echo shar: Extracting \"'slave.c'\" \(2687 characters\)
  698.   sed "s/^X//" >'slave.c' <<'END_OF_FILE'
  699. X/* Copyright 1990, Daniel J. Bernstein. All rights reserved. */
  700. X
  701. X#include "file.h"
  702. X#include "config.h"
  703. X#include "pty.h"
  704. X#include "tty.h"
  705. X#include "err.h"
  706. X#include "sig.h"
  707. X#include "slave.h"
  708. X#include "logs.h"
  709. X
  710. Xvoid slave(fnsty,arg)
  711. Xchar *fnsty;
  712. Xchar **arg;
  713. X{
  714. X sig_ignore(SIGTTOU);
  715. X sig_ignore(SIGTTIN);
  716. X
  717. X if (fdtty > -1)
  718. X  {
  719. X   (void) tty_dissoc(fdtty); /* must succeed */
  720. X   (void) close(fdtty);
  721. X  }
  722. X if (fdre > -1)
  723. X   (void) close(fdre);
  724. X (void) close(fdin);
  725. X (void) close(fdout);
  726. X (void) close(fdmty);
  727. X (void) close(fdsty);
  728. X (void) close(0);
  729. X (void) close(1);
  730. X if (flagsameerr < 2)
  731. X   (void) close(2);
  732. X if (flagsameerr < 1)
  733. X  {
  734. X   (void) close(3);
  735. X   for (fdout = getdtablesize();fdout > 3;fdout--)
  736. X     (void) close(fdout);
  737. X  }
  738. X
  739. X if (open(fnsty,O_RDONLY) != 0)
  740. X   fatalerrp(1,"pty: fatal: cannot reopen pty for input",errno);
  741. X if (open(fnsty,O_WRONLY) != 1)
  742. X     fatalerrp(1,"pty: fatal: cannot reopen pty for output",errno);
  743. X if (flagsameerr < 2)
  744. X   if (open(fnsty,(flagxerrwo ? O_WRONLY : O_RDWR)) != 2)
  745. X     fatalerrp(1,"pty: fatal: cannot reopen pty for stderr",errno);
  746. X if (flagsameerr < 1)
  747. X   if (open("/dev/tty",O_RDWR) != 3)
  748. X     fatalerrp(1,"pty: fatal: cannot reopen pty for /dev/tty",errno);
  749. X
  750. X if ((fdtty = open("/dev/tty",O_RDWR)) == -1)
  751. X   fatalerrp(1,"pty: fatal: cannot reopen pty for temporary /dev/tty",errno);
  752. X
  753. X if (setpgrp(0,getpid()) == -1)
  754. X   fatalerr(1,"pty: fatal: cannot set process group\n");
  755. X if (tty_setpgrp(fdtty,getpid()) == -1)
  756. X   fatalerrp(1,"pty: fatal: cannot set pty process group",errno);
  757. X if (tty_setmodes(fdtty,&tmopty) == -1)
  758. X   fatalerr(1,"pty: fatal: cannot set pty modes\n");
  759. X if (flagxexcl)
  760. X   if (tty_setexcl(fdtty) == -1)
  761. X     fatalerr(1,"pty: fatal: cannot set exclusive use on pty\n");
  762. X
  763. X (void) fchmod(0,USEDPTYMODE);
  764. X
  765. X if (flagxchown)
  766. X   (void) fchown(0,uid,PTYGROUP);
  767. X
  768. X (void) close(fdtty);
  769. X
  770. X date = now(); /* could use original date instead */
  771. X
  772. X if (flagxutmp)
  773. X  {
  774. X   if (flagverbose)
  775. X     warnerr2("%s","pty: writing utmp entry\n");
  776. X   if (utmp(fnsty + PTYUTMP_OFFSET,username,PTYUTMP_HOST,date) == -1)
  777. X     warnerr2("pty: warning: cannot write %s utmp entry\n",fnsty);
  778. X  }
  779. X
  780. X if (flagxwtmp)
  781. X  {
  782. X   if (flagverbose)
  783. X     warnerr2("%s","pty: writing wtmp entry\n");
  784. X   if (wtmp(fnsty + PTYWTMP_OFFSET,username,PTYWTMP_HOST,date) == -1)
  785. X     warnerr2("pty: warning: cannot write %s wtmp entry\n",fnsty);
  786. X  }
  787. X
  788. X if (setreuid(uid,uid) == -1)
  789. X   /* We absolutely refuse to exec while setuid. */
  790. X   fatalerrp(1,"pty: fatal: cannot setreuid",errno);
  791. X
  792. X sig_restore();
  793. X if (flagverbose)
  794. X   warnerr2("pty: executing program %s\n",arg[0]);
  795. X (void) execvp(arg[0],arg);
  796. X fatalerr2p(1,"pty: fatal: cannot execute %s",arg[0],errno);
  797. X /*NOTREACHED*/
  798. X}
  799. END_OF_FILE
  800.   if test 2687 -ne `wc -c <'slave.c'`; then
  801.     echo shar: \"'slave.c'\" unpacked with wrong size!
  802.   fi
  803.   # end of 'slave.c'
  804. fi
  805. if test -f 'texts.c' -a "${1}" != "-c" ; then 
  806.   echo shar: Will not clobber existing file \"'texts.c'\"
  807. else
  808.   echo shar: Extracting \"'texts.c'\" \(3819 characters\)
  809.   sed "s/^X//" >'texts.c' <<'END_OF_FILE'
  810. X/* Copyright 1990, Daniel J. Bernstein. All rights reserved. */
  811. X
  812. X#include "config.h"
  813. X#include "texts.h"
  814. X
  815. Xchar *ptyauthor[] = {
  816. X"pty was written by Daniel J. Bernstein." ,
  817. X"Internet address: brnstnd@acf10.nyu.edu." ,
  818. X0 } ;
  819. X
  820. Xchar *ptyversion[] = {
  821. X"pty version 3.001, August 21, 1990." ,
  822. X"Copyright (c) 1990, Daniel J. Bernstein." ,
  823. X"All rights reserved." ,
  824. X0 } ;
  825. X
  826. Xchar *ptycopyright[] = {
  827. X"pty version 3.001, August 21, 1990." ,
  828. X"Copyright (c) 1990, Daniel J. Bernstein." ,
  829. X"All rights reserved." ,
  830. X"" ,
  831. X"I want this program to be distributed freely in original form." ,
  832. X"" ,
  833. X"Once you've received a legal copy of this program, you can use it." ,
  834. X"Forever. Nobody can take that right away from you. You can make changes" ,
  835. X"and backup copies for your use (or, if you're an organization, for the" ,
  836. X"use of everyone in the organization). You can distribute patches (though" ,
  837. X"not patched versions). You'd have all these rights even if I didn't tell" ,
  838. X"you about them." ,
  839. X"" ,
  840. X"I do grant you further rights, as detailed in the source package. Don't" ,
  841. X"worry about them unless you're planning to distribute further copies." ,
  842. X"" ,
  843. X"If you have questions about this program or about this notice, or if you" ,
  844. X"would like additional rights beyond those granted above, or if you have" ,
  845. X"a patch that you don't mind sharing, please contact me on the Internet" ,
  846. X"at brnstnd@acf10.nyu.edu." ,
  847. X0 } ;
  848. X
  849. Xchar *ptywarranty[] = {
  850. X"Daniel J. Bernstein disclaims all warranties to the extent permitted" ,
  851. X"by applicable law. He is not and shall not be liable for any damages" ,
  852. X"arising from the use of this program. This disclaimer shall be governed" ,
  853. X"by the laws of the state of New York." ,
  854. X"" ,
  855. X"In other words, use this program at your own risk." ,
  856. X"" ,
  857. X"If you have questions about this program or about this disclaimer of" ,
  858. X"warranty, please feel free to contact me at brnstnd@acf10.nyu.edu on" ,
  859. X"the Internet." ,
  860. X0 } ;
  861. X
  862. Xchar *ptyusage[] = {
  863. X"Usage: pty [ -qQve3EdDjJsStT0FACHUVW ] [ -fn ] [ -p[cCdDeEnNrRsS0] ]" ,
  864. X"           [ -x[cCeEnNoOrRsSuUwWxX ] program [ arg ... ]" ,
  865. X"Help:  pty -H" ,
  866. X0 } ;
  867. X
  868. Xchar *ptyhelp[] = {
  869. X"pty runs a program under a pseudo-terminal session." ,
  870. X"pty -ACHUVW: print authorship notice, copyright notice, this notice," ,
  871. X"             short usage summary, version number, disclaimer of warranty" ,
  872. X"pty [-qQve3EdDjJsStT0F] [-fn] [-p[cCdDeEnNrRsS0]] [-x[cCeEnNoOrRsSuUwWxX]]" ,
  873. X"  program [arg...]: run program under a pseudo-terminal" ,
  874. X"Options processed l to r. Capitals turn things off. Here + means default." ,
  875. X"-q: quiet (nothing on stderr)   -e: leave fds 2 & 3    0=eSTp0  p0=pcrEN" ,
  876. X"+Q: normal level of verbosity   -3: leave fd 3 only    d=dJT D=Djt    d=>T" ,
  877. X"-v: complain about everything   +E: 2 & 3 both->pty    s=sxu S=SxU    s=>E" ,
  878. X"-d: we are detached    +j: job control    +t: change orig tty to char mode" ,
  879. X"+D: we have ctrl tty   -J: ignore stops   -T: leave orig tty alone" ,
  880. X"-s: session (allow disconnect & reconnect)   -fn: pass pty fds up fd n" ,
  881. X"+S: no session: disconnect will send HUP     +F: no -f" ,
  882. X"-p[cCdDeEnNrRsS]: set pty modes; defaults taken from original tty if -D" ,
  883. X"  c: cbreak, character mode  +n: change return to newline  +e: echo" ,
  884. X" +d: new line discipline      r: raw, no keyboard signals  +s: screen, crt" ,
  885. X"-x[cCeEnNoOrRsSuUwWxX]: security/experimental/extended, may be restricted" ,
  886. X"  c: change pty owner   e: pty's stderr write-only       x: set TIOCEXCL" ,
  887. X" +s: setuid, safer     +n: check if anyone has pty open  u: use /etc/utmp" ,
  888. X" +r: pick random pty    o: skip if anyone has pty open   w: use /etc/wtmp" ,
  889. X"If you have questions about or suggestions for pty, please feel free" ,
  890. X"to contact the author, Daniel J. Bernstein, at brnstnd@acf10.nyu.edu" ,
  891. X"on the Internet." ,
  892. X0 } ;
  893. X/* I still can't believe ptyhelp fits. :-) */
  894. END_OF_FILE
  895.   if test 3819 -ne `wc -c <'texts.c'`; then
  896.     echo shar: \"'texts.c'\" unpacked with wrong size!
  897.   fi
  898.   # end of 'texts.c'
  899. fi
  900. if test -f 'util/biff.c' -a "${1}" != "-c" ; then 
  901.   echo shar: Will not clobber existing file \"'util/biff.c'\"
  902. else
  903.   echo shar: Extracting \"'util/biff.c'\" \(1038 characters\)
  904.   sed "s/^X//" >'util/biff.c' <<'END_OF_FILE'
  905. X/* Public domain. */
  906. X
  907. X#include <sys/types.h>
  908. X#include <sys/stat.h>
  909. X#include <stdio.h>
  910. X#include "sessutil.h"
  911. Xextern unsigned short getuid();
  912. X
  913. X#define FOO (void) fstat(0,&st); \
  914. Xif (which) (void) fchmod(0,(int) (st.st_mode | 0100)); \
  915. Xelse (void) fchmod(0,(int) (st.st_mode & ~0100));
  916. X
  917. Xmain(argc,argv)
  918. Xint argc;
  919. Xchar *argv[];
  920. X{
  921. X struct stat st;
  922. X struct pty_session ps;
  923. X int uid;
  924. X int which;
  925. X
  926. X uid = getuid();
  927. X
  928. X if (argc == 1)
  929. X  {
  930. X   (void) setreuid(uid,uid);
  931. X   (void) fstat(0,&st);
  932. X   if (st.st_mode & 0100)
  933. X     (void) printf("is y\n");
  934. X   else
  935. X     (void) printf("is n\n");
  936. X  }
  937. X else
  938. X  {
  939. X   switch(argv[1][0])
  940. X    {
  941. X     case 'y': which = 1; break;
  942. X     case 'n': which = 0; break;
  943. X     default: (void) fprintf(stderr,"usage: biff [y] [n]\n"); exit(1);
  944. X    }
  945. X   if (pty_get_sess(0,uid,&ps) == -1)
  946. X    {
  947. X     (void) setreuid(uid,uid);
  948. X     FOO
  949. X    }
  950. X   else
  951. X     if (ps.uid != uid)
  952. X       (void) fprintf(stderr,"not your session\n");
  953. X     else
  954. X      {
  955. X       FOO
  956. X       (void) setreuid(uid,uid);
  957. X       FOO
  958. X      }
  959. X  }
  960. X (void) exit(0);
  961. X}
  962. END_OF_FILE
  963.   if test 1038 -ne `wc -c <'util/biff.c'`; then
  964.     echo shar: \"'util/biff.c'\" unpacked with wrong size!
  965.   fi
  966.   # end of 'util/biff.c'
  967. fi
  968. if test -f 'util/sesslist.c' -a "${1}" != "-c" ; then 
  969.   echo shar: Will not clobber existing file \"'util/sesslist.c'\"
  970. else
  971.   echo shar: Extracting \"'util/sesslist.c'\" \(2102 characters\)
  972.   sed "s/^X//" >'util/sesslist.c' <<'END_OF_FILE'
  973. X/* Public domain. */
  974. X
  975. X#include <sys/types.h>
  976. X#include <sys/file.h>
  977. X#ifdef BSD
  978. X#include <limits.h>
  979. X#endif
  980. X#include <sys/dir.h>
  981. X#include <stdio.h>
  982. X#include "sessutil.h"
  983. Xextern unsigned short getuid();
  984. X
  985. Xmain()
  986. X{
  987. X int uid;
  988. X DIR *dirp;
  989. X struct direct *dp;
  990. X int fd;
  991. X int intbuf[100];
  992. X char *buf = (char *) intbuf;
  993. X int r;
  994. X
  995. X uid = getuid();
  996. X
  997. X if (pty_sessdir(uid) == -1)
  998. X  {
  999. X   (void) fputs("sesslist: fatal: cannot change to session directory\n",stderr);
  1000. X   (void) exit(1);
  1001. X  }
  1002. X dirp = opendir(".");
  1003. X while (dp = readdir(dirp))
  1004. X  {
  1005. X   if (!strncmp(dp->d_name,"re.",3))
  1006. X     (void) printf("session %s disconnected\n",dp->d_name + 3);
  1007. X   else if (!strncmp(dp->d_name,"sess.",5))
  1008. X    {
  1009. X     if ((fd = open(dp->d_name,O_RDONLY)) == -1)
  1010. X       (void) fprintf(stderr,
  1011. X          "sesslist: warning: cannot open %s\n",dp->d_name);
  1012. X     else
  1013. X      {
  1014. X       r = read(fd,buf,99); /* anything up to sizeof(intbuf) - 1 */
  1015. X       if (r < 4 * sizeof(int))
  1016. X         (void) fprintf(stderr,
  1017. X            "sesslist: warning: cannot read %s\n",dp->d_name);
  1018. X       else if (r == 4 * sizeof(int))
  1019. X     (void) printf("session %s sigler %d master %d slave %d\n",
  1020. X        dp->d_name + 5,intbuf[1],intbuf[2],intbuf[3]);
  1021. X       else
  1022. X    {
  1023. X     buf[r] = '\0';
  1024. X     (void) printf("session %s sigler %d master %d slave %d: %s\n",
  1025. X        dp->d_name + 5,intbuf[1],intbuf[2],intbuf[3],
  1026. X        buf + 4 * sizeof(int));
  1027. X    }
  1028. X       (void) close(fd);
  1029. X      }
  1030. X    }
  1031. X   else if (!strncmp(dp->d_name,"sig.",4))
  1032. X    {
  1033. X     if ((fd = open(dp->d_name,O_RDONLY)) == -1)
  1034. X       (void) fprintf(stderr,
  1035. X          "sesslist: warning: cannot open %s\n",dp->d_name);
  1036. X     else
  1037. X      {
  1038. X       r = read(fd,buf,99);
  1039. X       if (r < 9)
  1040. X         (void) fprintf(stderr,
  1041. X            "sesslist: warning: cannot read %s\n",dp->d_name);
  1042. X       else
  1043. X    {
  1044. X     buf[r] = '\0';
  1045. X     (void) printf("session %s will drop into session %s\n",
  1046. X        dp->d_name + 4,buf + 8);
  1047. X    }
  1048. X       (void) close(fd);
  1049. X      }
  1050. X    }
  1051. X   else if (!strncmp(dp->d_name,".",1))
  1052. X     ;
  1053. X   else if (!strncmp(dp->d_name,"..",2))
  1054. X     ;
  1055. X   else
  1056. X     (void) fprintf(stderr,
  1057. X        "sesslist: warning: unknown file type %s\n",dp->d_name);
  1058. X  }
  1059. X (void) exit(0);
  1060. X}
  1061. END_OF_FILE
  1062.   if test 2102 -ne `wc -c <'util/sesslist.c'`; then
  1063.     echo shar: \"'util/sesslist.c'\" unpacked with wrong size!
  1064.   fi
  1065.   # end of 'util/sesslist.c'
  1066. fi
  1067. if test -f 'util/sessuser.1' -a "${1}" != "-c" ; then 
  1068.   echo shar: Will not clobber existing file \"'util/sessuser.1'\"
  1069. else
  1070.   echo shar: Extracting \"'util/sessuser.1'\" \(2006 characters\)
  1071.   sed "s/^X//" >'util/sessuser.1' <<'END_OF_FILE'
  1072. X.TH sessuser 1
  1073. X.SH NAME
  1074. Xsessuser \- rectify ownership of current pty session
  1075. X.SH SYNOPSIS
  1076. X.B sessuser
  1077. X.SH DESCRIPTION
  1078. X.I sessuser
  1079. Xtransfers ownership of the current pty session
  1080. Xto the user who owns the actual pseudo-terminal file.
  1081. X.PP
  1082. X.I sessuser
  1083. Xis useful in adapting
  1084. X.I pty
  1085. Xto old, inconsistent models of logging in.
  1086. XAn incoming user should be forced to type 
  1087. Xa correct password before the login process
  1088. Xeven touches a terminal;
  1089. Xhe should be given a tty
  1090. Xonly after his identity is established.
  1091. XInstead,
  1092. Xusers are given terminals
  1093. X(as root)
  1094. Xfirst.
  1095. XWhen
  1096. Xthese obsolete programs are modified
  1097. Xto let
  1098. X.I pty
  1099. Xallocate a pseudo-terminal,
  1100. Xtheir order of operations is still the same,
  1101. Xand
  1102. X.I pty
  1103. Xstill thinks the session is owned by root.
  1104. XHowever,
  1105. Xthe login program
  1106. Xdoes change the ownership of the
  1107. Xpseudo-terminal file to the user.
  1108. X.I sessuser
  1109. Xcommunicates this change to
  1110. Xthe
  1111. X.I pty
  1112. Xmanager,
  1113. Xso that
  1114. X.I sesslist,
  1115. X.I sessname,
  1116. X.I sesskill,
  1117. X.I disconnect,
  1118. Xand 
  1119. X.I reconnect
  1120. Xwill work.
  1121. X.PP
  1122. X.I xsessuser
  1123. Xis just like
  1124. X.I sessuser
  1125. Xbut applies to sessions started with
  1126. X.B\-xS.
  1127. XIt should never be needed, but it is
  1128. Xprovided for consistency.
  1129. X.SH DIAGNOSTICS
  1130. X.TP
  1131. X.I cannot find session
  1132. XThe standard input to
  1133. X.I sessuser
  1134. Xis not a session owned by
  1135. Xthe effective uid of
  1136. X.I sessuser.
  1137. X.TP
  1138. X.I cannot stat tty
  1139. XThis cannot happen.
  1140. X.TP
  1141. X.I you don't own tty
  1142. XYou don't own the pseudo-terminal file.
  1143. X.TP
  1144. X.I not child of session slave
  1145. XThe parent to
  1146. X.I sessuser
  1147. Xis not the head process in the session.
  1148. X.TP
  1149. X.I cannot find your username
  1150. XYou're not listed in
  1151. X/etc/passwd.
  1152. X.TP
  1153. X.I cannot open /etc/utmp
  1154. XSelf-explanatory.
  1155. X.TP
  1156. X.I cannot set session
  1157. X.I sessuser
  1158. Xis unable to record the
  1159. Xchange in session ownership.
  1160. X.TP
  1161. X.I cannot communicate new user
  1162. X.I sessuser
  1163. Xis unable to communicate with
  1164. Xthe pseudo-terminal
  1165. Xmanager.
  1166. X.SH RESTRICTIONS
  1167. X.I sessuser
  1168. Xrequires that the session be
  1169. Xlisted in
  1170. X/etc/utmp.
  1171. XIf it is not,
  1172. Xor if it is not listed under
  1173. Xthe correct username,
  1174. X.I sessuser
  1175. Xwill exit silently
  1176. Xwith exit code 1.
  1177. X.SH "SEE ALSO"
  1178. Xpty(1),
  1179. Xsess(1)
  1180. END_OF_FILE
  1181.   if test 2006 -ne `wc -c <'util/sessuser.1'`; then
  1182.     echo shar: \"'util/sessuser.1'\" unpacked with wrong size!
  1183.   fi
  1184.   # end of 'util/sessuser.1'
  1185. fi
  1186. if test -f 'util/sessuser.c' -a "${1}" != "-c" ; then 
  1187.   echo shar: Will not clobber existing file \"'util/sessuser.c'\"
  1188. else
  1189.   echo shar: Extracting \"'util/sessuser.c'\" \(1872 characters\)
  1190.   sed "s/^X//" >'util/sessuser.c' <<'END_OF_FILE'
  1191. X/* Public domain. */
  1192. X
  1193. X#include <sys/types.h>
  1194. X#include <sys/stat.h>
  1195. X#include <stdio.h>
  1196. X#include <utmp.h>
  1197. X#include <pwd.h>
  1198. X#include <signal.h>
  1199. X#include <strings.h>
  1200. X#include "sessutil.h"
  1201. Xextern unsigned short getuid();
  1202. Xextern unsigned short geteuid();
  1203. X#define PTYUTMP_FILE "/etc/utmp"
  1204. X
  1205. Xmain()
  1206. X{
  1207. X struct pty_session ps;
  1208. X int uid;
  1209. X int euid;
  1210. X register FILE *fi;
  1211. X struct utmp ut;
  1212. X struct stat st;
  1213. X struct passwd *pw;
  1214. X char *username;
  1215. X
  1216. X uid = getuid();
  1217. X euid = geteuid();
  1218. X
  1219. X if (pty_get_sess(0,euid,&ps) == -1) /* i.e., as root */
  1220. X  {
  1221. X   (void) fputs("sessuser: fatal: cannot find session\n",stderr);
  1222. X   (void) exit(1);
  1223. X  }
  1224. X if (fstat(0,&st) == -1)
  1225. X  {
  1226. X   (void) fputs("sessuser: fatal: cannot stat tty\n",stderr);
  1227. X   (void) exit(1);
  1228. X  }
  1229. X if (st.st_uid != uid)
  1230. X  {
  1231. X   (void) fputs("sessuser: fatal: you don't own tty\n",stderr);
  1232. X   (void) exit(1);
  1233. X  }
  1234. X if (ps.slavepid != getppid())
  1235. X  {
  1236. X   (void) fputs("sessuser: fatal: not child of session slave\n",stderr);
  1237. X   (void) exit(1);
  1238. X  }
  1239. X if (!(pw = getpwuid(uid)))
  1240. X  {
  1241. X   (void) fputs("sessuser: fatal: cannot find your username\n",stderr);
  1242. X   (void) exit(1);
  1243. X  }
  1244. X username = pw->pw_name;
  1245. X if (!(fi = fopen(PTYUTMP_FILE,"r")))
  1246. X  {
  1247. X   (void) perror("sessuser: fatal: cannot open /etc/utmp");
  1248. X   (void) exit(1);
  1249. X  }
  1250. X else
  1251. X   while (fread((char *) &ut,sizeof(ut),1,fi))
  1252. X     if ((ut.ut_line[3] == ps.ext1) && (ut.ut_line[4] == ps.ext2)
  1253. X       &&(ut.ut_line[5] == '\0'))
  1254. X       if (!strncmp(ut.ut_name,username,8))
  1255. X    {
  1256. X     ps.uid = uid;
  1257. X     if (pty_set_sess(0,uid,&ps) == -1)
  1258. X      {
  1259. X           (void) fputs("sessuser: fatal: cannot set session\n",stderr);
  1260. X           (void) exit(1);
  1261. X      }
  1262. X     if (kill(ps.masterpid,SIGUSR2) == -1)
  1263. X      {
  1264. X           (void) fputs("sessuser: fatal: cannot communicate new user\n",stderr);
  1265. X           (void) exit(1);
  1266. X      }
  1267. X     (void) fchown(0,euid,-1);
  1268. X     (void) exit(0);
  1269. X    }
  1270. X       else
  1271. X     (void) exit(1);
  1272. X (void) exit(1);
  1273. X}
  1274. END_OF_FILE
  1275.   if test 1872 -ne `wc -c <'util/sessuser.c'`; then
  1276.     echo shar: \"'util/sessuser.c'\" unpacked with wrong size!
  1277.   fi
  1278.   # end of 'util/sessuser.c'
  1279. fi
  1280. if test -f 'util/sessutil.c' -a "${1}" != "-c" ; then 
  1281.   echo shar: Will not clobber existing file \"'util/sessutil.c'\"
  1282. else
  1283.   echo shar: Extracting \"'util/sessutil.c'\" \(3786 characters\)
  1284.   sed "s/^X//" >'util/sessutil.c' <<'END_OF_FILE'
  1285. X/* Public domain. */
  1286. X
  1287. X#include "sessutil.h"
  1288. X#include <sys/types.h>
  1289. X#include <sys/stat.h>
  1290. X#include <sys/file.h>
  1291. X#ifdef BSD
  1292. X#include <limits.h>
  1293. X#endif
  1294. X#include <stdio.h>
  1295. Xextern char *ttyname();
  1296. Xextern long lseek();
  1297. X
  1298. X/* Will have to change ttyn indices if DEVSTY changes. */
  1299. X
  1300. Xint pty_sessdir(uid)
  1301. Xint uid;
  1302. X{
  1303. X char foo[50];
  1304. X
  1305. X (void) sprintf(foo,"/usr/etc/pty/%d",uid);
  1306. X return chdir(foo);
  1307. X}
  1308. X
  1309. Xint pty_get_sess(fd,uid,ps)
  1310. Xint fd;
  1311. Xint uid;
  1312. Xstruct pty_session *ps;
  1313. X{
  1314. X char *ttyn;
  1315. X
  1316. X if (ttyn = ttyname(fd))
  1317. X   return pty_get_sessbyext(ttyn[8],ttyn[9],uid,ps);
  1318. X return -1;
  1319. X}
  1320. X
  1321. Xint pty_get_sessbyext(ext1,ext2,uid,ps)
  1322. Xchar ext1;
  1323. Xchar ext2;
  1324. Xint uid;
  1325. Xstruct pty_session *ps;
  1326. X{
  1327. X char foo[50];
  1328. X int fdsess;
  1329. X
  1330. X ps->ext1 = ext1;
  1331. X ps->ext2 = ext2;
  1332. X (void) sprintf(foo,"/usr/etc/pty/%d/sess.%c%c",uid,ps->ext1,ps->ext2);
  1333. X if ((fdsess = open(foo,O_RDONLY)) != -1)
  1334. X  {
  1335. X   if ((read(fdsess,(char *) &ps->uid,sizeof(int)) == sizeof(int))
  1336. X     &&(read(fdsess,(char *) &ps->siglerpid,sizeof(int)) == sizeof(int))
  1337. X     &&(read(fdsess,(char *) &ps->masterpid,sizeof(int)) == sizeof(int))
  1338. X     &&(read(fdsess,(char *) &ps->slavepid,sizeof(int)) == sizeof(int)))
  1339. X    {
  1340. X     (void) close(fdsess);
  1341. X     return 0;
  1342. X    }
  1343. X   (void) close(fdsess);
  1344. X  }
  1345. X return -1;
  1346. X}
  1347. X
  1348. Xint pty_set_sess(fd,uid,ps)
  1349. Xint fd;
  1350. Xint uid;
  1351. Xstruct pty_session *ps;
  1352. X{
  1353. X char *ttyn;
  1354. X char foo[50];
  1355. X int fdsess;
  1356. X
  1357. X if (ttyn = ttyname(fd))
  1358. X  {
  1359. X   ps->ext1 = ttyn[8];
  1360. X   ps->ext2 = ttyn[9];
  1361. X   (void) sprintf(foo,"/usr/etc/pty/%d/sess.%c%c",uid,ps->ext1,ps->ext2);
  1362. X   if ((fdsess = open(foo,O_WRONLY)) != -1)
  1363. X    {
  1364. X     if ((write(fdsess,(char *) &ps->uid,sizeof(int)) == sizeof(int))
  1365. X       &&(write(fdsess,(char *) &ps->siglerpid,sizeof(int)) == sizeof(int))
  1366. X       &&(write(fdsess,(char *) &ps->masterpid,sizeof(int)) == sizeof(int))
  1367. X       &&(write(fdsess,(char *) &ps->slavepid,sizeof(int)) == sizeof(int)))
  1368. X      {
  1369. X       (void) close(fdsess);
  1370. X       return 0;
  1371. X      }
  1372. X     (void) close(fdsess);
  1373. X    }
  1374. X  }
  1375. X return -1;
  1376. X}
  1377. X
  1378. Xint pty_get_sessname(fd,uid,buf,len)
  1379. Xint fd;
  1380. Xint uid;
  1381. Xchar *buf;
  1382. Xint len;
  1383. X{
  1384. X char *ttyn;
  1385. X char foo[50];
  1386. X int fdsess;
  1387. X int r;
  1388. X
  1389. X if (ttyn = ttyname(fd))
  1390. X  {
  1391. X   (void) sprintf(foo,"/usr/etc/pty/%d/sess.%c%c",uid,ttyn[8],ttyn[9]);
  1392. X   if ((fdsess = open(foo,O_RDONLY)) != -1)
  1393. X    {
  1394. X     if (lseek(fdsess,(long) (4 * sizeof(int)),0) != (long) -1)
  1395. X       if ((r = read(fdsess,buf,len - 1)) > 0)
  1396. X    { /* could make that != -1. This way, default session is unnamed. */
  1397. X     buf[r] = '\0';
  1398. X     (void) close(fdsess);
  1399. X     return 0;
  1400. X    }
  1401. X     (void) close(fdsess);
  1402. X    }
  1403. X  }
  1404. X return -1;
  1405. X}
  1406. X
  1407. Xint pty_set_sessname(fd,uid,buf,len)
  1408. Xint fd;
  1409. Xint uid;
  1410. Xchar *buf;
  1411. Xint len;
  1412. X{
  1413. X char *ttyn;
  1414. X char foo[50];
  1415. X int fdsess;
  1416. X
  1417. X if (ttyn = ttyname(fd))
  1418. X  {
  1419. X   (void) sprintf(foo,"/usr/etc/pty/%d/sess.%c%c",uid,ttyn[8],ttyn[9]);
  1420. X   if ((fdsess = open(foo,O_WRONLY)) != -1)
  1421. X    {
  1422. X     if (lseek(fdsess,(long) (4 * sizeof(int)),0) != (long) -1)
  1423. X       if (write(fdsess,buf,len) != -1)
  1424. X    {
  1425. X     (void) close(fdsess);
  1426. X     return 0;
  1427. X    }
  1428. X     (void) close(fdsess);
  1429. X    }
  1430. X  }
  1431. X return -1;
  1432. X}
  1433. X
  1434. Xint pty_get_rebyext(ext1,ext2,uid)
  1435. Xchar ext1;
  1436. Xchar ext2;
  1437. Xint uid;
  1438. X{
  1439. X char foo[50];
  1440. X struct stat st;
  1441. X
  1442. X (void) sprintf(foo,"/usr/etc/pty/%d/re.%c%c",uid,ext1,ext2);
  1443. X return stat(foo,&st);
  1444. X}
  1445. X
  1446. Xint pty_set_sig(ext1,ext2,uid,ps)
  1447. Xchar ext1;
  1448. Xchar ext2;
  1449. Xint uid;
  1450. Xstruct pty_session *ps;
  1451. X{
  1452. X char foo[50];
  1453. X int fdsig;
  1454. X
  1455. X (void) sprintf(foo,"/usr/etc/pty/%d/sig.%c%c",uid,ps->ext1,ps->ext2);
  1456. X if ((fdsig = open(foo,O_WRONLY | O_CREAT | O_TRUNC,0600)) != -1)
  1457. X  {
  1458. X   (void) sprintf(foo,"/dev/tty%c%c",ext1,ext2);
  1459. X   if (write(fdsig,foo,11) == 11)
  1460. X    {
  1461. X     (void) close(fdsig);
  1462. X     return 0;
  1463. X    }
  1464. X   (void) close(fdsig);
  1465. X  }
  1466. X return -1;
  1467. X}
  1468. X
  1469. Xint pty_unset_sig(uid,ps)
  1470. Xint uid;
  1471. Xstruct pty_session *ps;
  1472. X{
  1473. X char foo[50];
  1474. X
  1475. X (void) sprintf(foo,"/usr/etc/pty/%d/sig.%c%c",uid,ps->ext1,ps->ext2);
  1476. X return unlink(foo);
  1477. X}
  1478. END_OF_FILE
  1479.   if test 3786 -ne `wc -c <'util/sessutil.c'`; then
  1480.     echo shar: \"'util/sessutil.c'\" unpacked with wrong size!
  1481.   fi
  1482.   # end of 'util/sessutil.c'
  1483. fi
  1484. if test -f 'util/write.c' -a "${1}" != "-c" ; then 
  1485.   echo shar: Will not clobber existing file \"'util/write.c'\"
  1486. else
  1487.   echo shar: Extracting \"'util/write.c'\" \(2728 characters\)
  1488.   sed "s/^X//" >'util/write.c' <<'END_OF_FILE'
  1489. X/* Public domain. */
  1490. X
  1491. X#include <sys/types.h>
  1492. X#include <sys/timeb.h>
  1493. X#include <sys/stat.h>
  1494. X#include <sys/file.h>
  1495. X#ifdef BSD
  1496. X#include <limits.h>
  1497. X#endif
  1498. X#include <stdio.h>
  1499. X#include <strings.h>
  1500. X#include <utmp.h>
  1501. X#include <pwd.h>
  1502. X#include <time.h>
  1503. X#include <ctype.h>
  1504. Xextern unsigned short getuid();
  1505. Xextern char *ttyname();
  1506. Xextern long time();
  1507. X#define PTYUTMP_FILE "/etc/utmp"
  1508. X
  1509. Xmain(argc,argv)
  1510. Xint argc;
  1511. Xchar *argv[];
  1512. X{ 
  1513. X register FILE *fi;
  1514. X struct utmp ut;
  1515. X char line[9];
  1516. X int lines = 0;
  1517. X char fntty[30];
  1518. X int fd;
  1519. X struct stat st;
  1520. X char buf[500];
  1521. X int offset;
  1522. X char *username;
  1523. X struct passwd *pw;
  1524. X char hostname[64];
  1525. X char *ttyn;
  1526. X long t;
  1527. X struct tm *tm;
  1528. X char *s;
  1529. X
  1530. X if (argc < 2)
  1531. X  {
  1532. X   (void) fprintf(stderr,"Usage: write user [ttyname]\n");
  1533. X   (void) exit(1);
  1534. X  }
  1535. X
  1536. X if (!(pw = getpwuid((int) getuid())))
  1537. X  {
  1538. X   (void) fprintf(stderr,"write: who are you?\n");
  1539. X   (void) exit(1);
  1540. X  }
  1541. X username = pw->pw_name;
  1542. X
  1543. X (void) gethostname(hostname,sizeof(hostname));
  1544. X
  1545. X if (!(ttyn = ttyname(2)))
  1546. X  {
  1547. X   (void) fprintf(stderr,"write: Can't find your tty\n");
  1548. X   (void) exit(1);
  1549. X  }
  1550. X
  1551. X t = time((long *) 0);
  1552. X tm = localtime(&t);
  1553. X
  1554. X if (fi = fopen(PTYUTMP_FILE,"r"))
  1555. X   while (fread((char *) &ut,sizeof(ut),1,fi))
  1556. X     if (!strncmp(ut.ut_name,argv[1],8))
  1557. X       if ((argc == 2) || (!strncmp(ut.ut_line,argv[2],8)))
  1558. X     if (!lines)
  1559. X      {
  1560. X       (void) strncpy(line,ut.ut_line,8);
  1561. X       line[8] = '\0';
  1562. X       lines = 1;
  1563. X      }
  1564. X     else
  1565. X       lines++;
  1566. X if (!lines)
  1567. X  {
  1568. X   if (argc == 2)
  1569. X     (void) fprintf(stderr,"write: %s not logged in\n",argv[1]);
  1570. X   else
  1571. X     (void) fprintf(stderr,"write: %s not logged in on tty %s\n",
  1572. X            argv[1],argv[2]);
  1573. X   (void) exit(1);
  1574. X  }
  1575. X if (lines > 1)
  1576. X   (void) fprintf(stderr,
  1577. X   "write: %s logged in more than once ... writing to %s\n",
  1578. X   argv[1],line);
  1579. X
  1580. X (void) sprintf(fntty,"/dev/%s",line);
  1581. X if ((fd = open(fntty,O_WRONLY)) == -1)
  1582. X  {
  1583. X   (void) fprintf(stderr,"write: Permission denied\n");
  1584. X   (void) exit(1);
  1585. X  }
  1586. X
  1587. X (void) sprintf(buf,"\nMessage from %s@%s on %s at %d:%02d ...\n",
  1588. X        username,hostname,ttyn + 5,tm->tm_hour,tm->tm_min);
  1589. X (void) write(fd,buf,strlen(buf));
  1590. X
  1591. X (void) sprintf(buf,"%s: ",username);
  1592. X offset = strlen(buf);
  1593. X
  1594. X while (fgets(buf + offset,sizeof(buf) - offset,stdin))
  1595. X  {
  1596. X   (void) fstat(fd,&st);
  1597. X   if (!(st.st_mode & 0020))
  1598. X    {
  1599. X     (void) fprintf(stderr,"write: Permission denied\n");
  1600. X     (void) exit(1);
  1601. X    }
  1602. X   for (s = buf;*s;s++)
  1603. X     if (((!isascii(*s) || !isprint(*s))) && (*s != '\n'))
  1604. X       *s = '^';
  1605. X   (void) write(fd,buf,strlen(buf));
  1606. X   (void) sleep(1);
  1607. X  }
  1608. X
  1609. X t = time((long *) 0);
  1610. X tm = localtime(&t);
  1611. X (void) sprintf(buf,"End of message from %s@%s on %s at %d:%02d\n",
  1612. X        username,hostname,ttyn + 5,tm->tm_hour,tm->tm_min);
  1613. X (void) write(fd,buf,strlen(buf));
  1614. X
  1615. X (void) exit(0);
  1616. X}
  1617. END_OF_FILE
  1618.   echo shar: 1 control character may be missing from \"'util/write.c'\"
  1619.   if test 2728 -ne `wc -c <'util/write.c'`; then
  1620.     echo shar: \"'util/write.c'\" unpacked with wrong size!
  1621.   fi
  1622.   # end of 'util/write.c'
  1623. fi
  1624. if test -f 'util/xsessutil.c' -a "${1}" != "-c" ; then 
  1625.   echo shar: Will not clobber existing file \"'util/xsessutil.c'\"
  1626. else
  1627.   echo shar: Extracting \"'util/xsessutil.c'\" \(4232 characters\)
  1628.   sed "s/^X//" >'util/xsessutil.c' <<'END_OF_FILE'
  1629. X/* Public domain. */
  1630. X
  1631. X#include "sessutil.h"
  1632. X#include <sys/types.h>
  1633. X#include <sys/stat.h>
  1634. X#include <sys/file.h>
  1635. X#ifdef BSD
  1636. X#include <limits.h>
  1637. X#endif
  1638. X#include <stdio.h>
  1639. Xextern char *ttyname();
  1640. Xextern long lseek();
  1641. Xextern char *getenv();
  1642. X
  1643. X/* Will have to change ttyn indices if DEVSTY changes. */
  1644. X
  1645. Xint pty_sessdir(uid)
  1646. Xint uid;
  1647. X{
  1648. X char foo[50];
  1649. X char *ho;
  1650. X
  1651. X if (!(ho = getenv("HOME")))
  1652. X   return -1;
  1653. X (void) sprintf(foo,"%s/.pty/%d",ho,uid);
  1654. X return chdir(foo);
  1655. X}
  1656. X
  1657. Xint pty_get_sess(fd,uid,ps)
  1658. Xint fd;
  1659. Xint uid;
  1660. Xstruct pty_session *ps;
  1661. X{
  1662. X char *ttyn;
  1663. X
  1664. X if (ttyn = ttyname(fd))
  1665. X   return pty_get_sessbyext(ttyn[8],ttyn[9],uid,ps);
  1666. X return -1;
  1667. X}
  1668. X
  1669. Xint pty_get_sessbyext(ext1,ext2,uid,ps)
  1670. Xchar ext1;
  1671. Xchar ext2;
  1672. Xint uid;
  1673. Xstruct pty_session *ps;
  1674. X{
  1675. X char foo[50];
  1676. X int fdsess;
  1677. X char *ho;
  1678. X
  1679. X if (!(ho = getenv("HOME")))
  1680. X   return -1;
  1681. X
  1682. X ps->ext1 = ext1;
  1683. X ps->ext2 = ext2;
  1684. X (void) sprintf(foo,"%s/.pty/%d/sess.%c%c",ho,uid,ps->ext1,ps->ext2);
  1685. X if ((fdsess = open(foo,O_RDONLY)) != -1)
  1686. X  {
  1687. X   if ((read(fdsess,(char *) &ps->uid,sizeof(int)) == sizeof(int))
  1688. X     &&(read(fdsess,(char *) &ps->siglerpid,sizeof(int)) == sizeof(int))
  1689. X     &&(read(fdsess,(char *) &ps->masterpid,sizeof(int)) == sizeof(int))
  1690. X     &&(read(fdsess,(char *) &ps->slavepid,sizeof(int)) == sizeof(int)))
  1691. X    {
  1692. X     (void) close(fdsess);
  1693. X     return 0;
  1694. X    }
  1695. X   (void) close(fdsess);
  1696. X  }
  1697. X return -1;
  1698. X}
  1699. X
  1700. Xint pty_set_sess(fd,uid,ps)
  1701. Xint fd;
  1702. Xint uid;
  1703. Xstruct pty_session *ps;
  1704. X{
  1705. X char *ttyn;
  1706. X char foo[50];
  1707. X int fdsess;
  1708. X char *ho;
  1709. X
  1710. X if (!(ho = getenv("HOME")))
  1711. X   return -1;
  1712. X
  1713. X if (ttyn = ttyname(fd))
  1714. X  {
  1715. X   ps->ext1 = ttyn[8];
  1716. X   ps->ext2 = ttyn[9];
  1717. X   (void) sprintf(foo,"%s/.pty/%d/sess.%c%c",ho,uid,ps->ext1,ps->ext2);
  1718. X   if ((fdsess = open(foo,O_WRONLY)) != -1)
  1719. X    {
  1720. X     if ((write(fdsess,(char *) &ps->uid,sizeof(int)) == sizeof(int))
  1721. X       &&(write(fdsess,(char *) &ps->siglerpid,sizeof(int)) == sizeof(int))
  1722. X       &&(write(fdsess,(char *) &ps->masterpid,sizeof(int)) == sizeof(int))
  1723. X       &&(write(fdsess,(char *) &ps->slavepid,sizeof(int)) == sizeof(int)))
  1724. X      {
  1725. X       (void) close(fdsess);
  1726. X       return 0;
  1727. X      }
  1728. X     (void) close(fdsess);
  1729. X    }
  1730. X  }
  1731. X return -1;
  1732. X}
  1733. X
  1734. Xint pty_get_sessname(fd,uid,buf,len)
  1735. Xint fd;
  1736. Xint uid;
  1737. Xchar *buf;
  1738. Xint len;
  1739. X{
  1740. X char *ttyn;
  1741. X char foo[50];
  1742. X int fdsess;
  1743. X int r;
  1744. X char *ho;
  1745. X
  1746. X if (!(ho = getenv("HOME")))
  1747. X   return -1;
  1748. X
  1749. X if (ttyn = ttyname(fd))
  1750. X  {
  1751. X   (void) sprintf(foo,"%s/.pty/%d/sess.%c%c",ho,uid,ttyn[8],ttyn[9]);
  1752. X   if ((fdsess = open(foo,O_RDONLY)) != -1)
  1753. X    {
  1754. X     if (lseek(fdsess,(long) (4 * sizeof(int)),0) != (long) -1)
  1755. X       if ((r = read(fdsess,buf,len - 1)) > 0)
  1756. X    { /* could make that != -1. This way, default session is unnamed. */
  1757. X     buf[r] = '\0';
  1758. X     (void) close(fdsess);
  1759. X     return 0;
  1760. X    }
  1761. X     (void) close(fdsess);
  1762. X    }
  1763. X  }
  1764. X return -1;
  1765. X}
  1766. X
  1767. Xint pty_set_sessname(fd,uid,buf,len)
  1768. Xint fd;
  1769. Xint uid;
  1770. Xchar *buf;
  1771. Xint len;
  1772. X{
  1773. X char *ttyn;
  1774. X char foo[50];
  1775. X int fdsess;
  1776. X char *ho;
  1777. X
  1778. X if (!(ho = getenv("HOME")))
  1779. X   return -1;
  1780. X
  1781. X if (ttyn = ttyname(fd))
  1782. X  {
  1783. X   (void) sprintf(foo,"%s/.pty/%d/sess.%c%c",ho,uid,ttyn[8],ttyn[9]);
  1784. X   if ((fdsess = open(foo,O_WRONLY)) != -1)
  1785. X    {
  1786. X     if (lseek(fdsess,(long) (4 * sizeof(int)),0) != (long) -1)
  1787. X       if (write(fdsess,buf,len) != -1)
  1788. X    {
  1789. X     (void) close(fdsess);
  1790. X     return 0;
  1791. X    }
  1792. X     (void) close(fdsess);
  1793. X    }
  1794. X  }
  1795. X return -1;
  1796. X}
  1797. X
  1798. Xint pty_get_rebyext(ext1,ext2,uid)
  1799. Xchar ext1;
  1800. Xchar ext2;
  1801. Xint uid;
  1802. X{
  1803. X char foo[50];
  1804. X struct stat st;
  1805. X char *ho;
  1806. X
  1807. X if (!(ho = getenv("HOME")))
  1808. X   return -1;
  1809. X
  1810. X (void) sprintf(foo,"%s/.pty/%d/re.%c%c",ho,uid,ext1,ext2);
  1811. X return stat(foo,&st);
  1812. X}
  1813. X
  1814. Xint pty_set_sig(ext1,ext2,uid,ps)
  1815. Xchar ext1;
  1816. Xchar ext2;
  1817. Xint uid;
  1818. Xstruct pty_session *ps;
  1819. X{
  1820. X char foo[50];
  1821. X int fdsig;
  1822. X char *ho;
  1823. X
  1824. X if (!(ho = getenv("HOME")))
  1825. X   return -1;
  1826. X
  1827. X (void) sprintf(foo,"%s/.pty/%d/sig.%c%c",ho,uid,ps->ext1,ps->ext2);
  1828. X if ((fdsig = open(foo,O_WRONLY | O_CREAT | O_TRUNC,0600)) != -1)
  1829. X  {
  1830. X   (void) sprintf(foo,"/dev/tty%c%c",ext1,ext2);
  1831. X   if (write(fdsig,foo,11) == 11)
  1832. X    {
  1833. X     (void) close(fdsig);
  1834. X     return 0;
  1835. X    }
  1836. X   (void) close(fdsig);
  1837. X  }
  1838. X return -1;
  1839. X}
  1840. X
  1841. Xint pty_unset_sig(uid,ps)
  1842. Xint uid;
  1843. Xstruct pty_session *ps;
  1844. X{
  1845. X char foo[50];
  1846. X char *ho;
  1847. X
  1848. X if (!(ho = getenv("HOME")))
  1849. X   return -1;
  1850. X
  1851. X (void) sprintf(foo,"%s/.pty/%d/sig.%c%c",ho,uid,ps->ext1,ps->ext2);
  1852. X return unlink(foo);
  1853. X}
  1854. END_OF_FILE
  1855.   if test 4232 -ne `wc -c <'util/xsessutil.c'`; then
  1856.     echo shar: \"'util/xsessutil.c'\" unpacked with wrong size!
  1857.   fi
  1858.   # end of 'util/xsessutil.c'
  1859. fi
  1860. echo shar: End of archive 4 \(of 6\).
  1861. cp /dev/null ark4isdone
  1862. MISSING=""
  1863. for I in 1 2 3 4 5 6 ; do
  1864.     if test ! -f ark${I}isdone ; then
  1865.     MISSING="${MISSING} ${I}"
  1866.     fi
  1867. done
  1868. if test "${MISSING}" = "" ; then
  1869.     echo You have unpacked all 6 archives.
  1870.     rm -f ark[1-9]isdone
  1871. else
  1872.     echo You still must unpack the following archives:
  1873.     echo "        " ${MISSING}
  1874. fi
  1875. exit 0
  1876. exit 0 # Just in case...
  1877. -- 
  1878. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  1879. Use a domain-based address or give alternate paths, or you may lose out.
  1880.